package cn.zglbk.generator.scan;
import cn.zglbk.data.csv.ClientTableFile;
import cn.zglbk.generator.model.ColumnEntity;
import cn.zglbk.generator.model.TableEntity;
import cn.zglbk.generator.model.TableModel;
import cn.zglbk.generator.utils.DateUtils;
import cn.zglbk.network.context.GatewayMessageContext;
import cn.zglbk.network.param.GameMessageHandler;
import cn.zglbk.network.param.GameMessageMapping;
import cn.zglbk.utils.TypeUtils;
import org.apache.commons.lang.StringUtils;
import org.reflections.Reflections;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * @author zglbk.cn
 * @email 1030681978@qq.com
 * @date 2020/11/6 17:20
 */
public class SpringControllerScan {

    public static void generatorTcp(String packagePath) {
        Reflections reflection = new Reflections(packagePath);
        // 根据注解，获取所有标记了这个注解的所有类的Class类
        Set<Class<?>> allGameMessageHandlerClass = reflection.getTypesAnnotatedWith(GameMessageHandler.class);
        //项目启动之后，调用此初始化方法
        //从spring 容器中获取所有被@GameMessageHandler标记的所有的类实例
        //使用stream并行处理遍历这些对象
        List<CsClassModel<CsMethodModel>> cs = new ArrayList<>();
        for (Class<?> bean : allGameMessageHandlerClass) {
            if (bean.isInterface()) {
                continue;
            }
            GameMessageHandler annotation = bean.getAnnotation(GameMessageHandler.class);
            if(annotation.proxyId() < 0){
                //事件监听
                continue;
            }
            CsClassModel<CsMethodModel> classModel = new CsClassModel<>();
            classModel.setClazzName(bean.getSimpleName());
            classModel.setServiceId(annotation.proxyId());
            classModel.setDatetime(DateUtils.format(new Date(System.currentTimeMillis()), DateUtils.DATE_TIME_PATTERN));
            classModel.setComments(annotation.commons());

            List<CsMethodModel> methodList = new ArrayList<>();
            Method[] methods = bean.getMethods();
            //遍历每个类中的方法
            for (Method method : methods) {
                GameMessageMapping mapping = method.getAnnotation(GameMessageMapping.class);
                if (mapping != null) {
                    //返回对象类型
                    CsMethodModel model1 = new CsMethodModel();
                    Class<?> respones = mapping.respones();
                    if (TypeUtils.isPrimitive(respones)) {
                        String returnType = TypeUtils.getArrType(respones.getName(), bean.getName(), method.getName());
                        model1.setReturnType(returnType);
                    } else if (respones == void.class) {
                        model1.setReturnType(respones.getName());
                    } else {
                        String str = StringUtils.substringAfterLast(respones.getTypeName(), ".");
                        str = StringUtils.replace(str, "$", ".");
                        model1.setReturnType(str);
                    }
                    Parameter[] parameters = method.getParameters();
                    if (parameters.length > 0) {
                        //第二个参数默认是线程上下文参数，所以客户端不需要生成

                        if (!parameters[0].getType().isAssignableFrom(GatewayMessageContext.class)) {
                            if (TypeUtils.isPrimitive(parameters[0].getType().getTypeName())) {
                                String returnType = TypeUtils.getArrType(parameters[0].getType().getTypeName(), bean.getClass().getName(), method.getName());
                                model1.setParamType(returnType);
                            } else {
                                String str = StringUtils.substringAfterLast(parameters[0].getType().getTypeName(), ".");
                                str = StringUtils.replace(str, "$", ".");
                                model1.setParamType(str);
                            }
                            model1.setParamName(parameters[0].getName());
                        } else {
                            model1.setParamName("");
                            model1.setParamType("");
                        }
                    } else {
                        model1.setParamName("");
                        model1.setParamType("");
                    }
                    model1.setMethodCommons(mapping.commons());
                    model1.setMethodName(method.getName());
                    model1.setMessageId(mapping.messageId());
                    methodList.add(model1);
                }
            }
            classModel.setColumns(methodList);
            cs.add(classModel);
        }
        //模板生成
        CsGenerator.generatorCode(cs, 1);
    }

    /**
     * 接口上的注解
     */
    public static void generatorCsBroadcast(String packagePath) {
        Reflections reflection = new Reflections(packagePath);
        // 根据注解，获取所有标记了这个注解的所有类的Class类
        Set<Class<?>> allGameMessageHandlerClass = reflection.getTypesAnnotatedWith(GameMessageHandler.class);
        //生cs和java
        if (allGameMessageHandlerClass != null) {
            List<CsClassModel<CsMethodModel>> cs = new ArrayList<>();
            List<TableEntity> java = new ArrayList<>();
            for (Class<?> bean : allGameMessageHandlerClass) {
                if (!bean.isInterface()) {
                    continue;
                }
                generatorJava(bean, java);
                GameMessageHandler annotation = bean.getAnnotation(GameMessageHandler.class);
                CsClassModel<CsMethodModel> classModel = new CsClassModel<>();
                classModel.setClazzName(bean.getSimpleName());
                classModel.setServiceId(annotation.proxyId());
                classModel.setDatetime(DateUtils.format(new Date(System.currentTimeMillis()), DateUtils.DATE_TIME_PATTERN));
                classModel.setComments(annotation.commons());
                List<CsMethodModel> methodList = new ArrayList<>();
                Method[] methods = bean.getMethods();
                //遍历每个类中的方法
                for (Method method : methods) {
                    GameMessageMapping mapping = method.getAnnotation(GameMessageMapping.class);
                    if (mapping != null) {
                        //返回对象类型
                        CsMethodModel model1 = new CsMethodModel();
                        Parameter[] parameters = method.getParameters();
                        if (parameters.length > 0) {
                            //第二个参数默认是线程上下文参数，所以客户端不需要生成
                            if (!parameters[0].getType().isAssignableFrom(GatewayMessageContext.class)) {
                                if (TypeUtils.isPrimitive(parameters[0].getType().getTypeName())) {
                                    String returnType = TypeUtils.getArrType(parameters[0].getType().getTypeName(), bean.getName(), method.getName());
                                    model1.setParamType(returnType);
                                } else {
                                    String str = StringUtils.substringAfterLast(parameters[0].getType().getTypeName(), ".");
                                    str = StringUtils.replace(str, "$", ".");
                                    model1.setParamType(str);
                                }
                                model1.setParamName(parameters[0].getName());
                            } else {
                                model1.setParamName("");
                                model1.setParamType("");
                            }
                        } else {
                            model1.setParamName("");
                            model1.setParamType("");
                        }
                        model1.setMethodCommons(mapping.commons());
                        model1.setMethodName(method.getName());
                        model1.setMessageId(mapping.messageId());
                        methodList.add(model1);
                    }
                }
                classModel.setColumns(methodList);
                cs.add(classModel);
            }
            //模板生成
            CsGenerator.generatorCode(cs, 2);
            JavaGenerator.generatorCode(java);
        }
    }

    private static void generatorJava(Class<?> bean, List<TableEntity> java) {
        GameMessageHandler annotation = bean.getAnnotation(GameMessageHandler.class);
        TableEntity classModel = new TableEntity();
        classModel.setInterfaceName(bean.getSimpleName());
        classModel.setClassName(bean.getSimpleName());
        classModel.setServiceId(annotation.proxyId());
        classModel.setDatetime(DateUtils.format(new Date(System.currentTimeMillis()), DateUtils.DATE_TIME_PATTERN));
        classModel.setComments(annotation.commons());
        List<ColumnEntity> methodList = new ArrayList<>();
        Method[] methods = bean.getMethods();
        //遍历每个类中的方法
        for (Method method : methods) {
            GameMessageMapping mapping = method.getAnnotation(GameMessageMapping.class);
            if (mapping != null) {
                //返回对象类型
                ColumnEntity model1 = new ColumnEntity();
                Parameter[] parameters = method.getParameters();
                if (parameters.length > 0) {
                    //第二个参数默认是线程上下文参数，所以客户端不需要生成
                    if (!parameters[0].getType().isAssignableFrom(GatewayMessageContext.class)) {
                        if (TypeUtils.isPrimitive(parameters[0].getType().getTypeName())) {
                            String returnType = TypeUtils.getArrType(parameters[0].getType().getTypeName(), bean.getName(), method.getName());
                            if (returnType.equals("string")) {
                                returnType = "String";
                            }
                            model1.setParamType(returnType);
                        } else {
                            String str = StringUtils.substringAfterLast(parameters[0].getType().getTypeName(), ".");
                            str = StringUtils.replace(str, "$", ".");
                            model1.setParamType(str);
                        }
                        model1.setParamName(parameters[0].getName());
                    } else {
                        model1.setParamName("");
                        model1.setParamType("");
                    }
                } else {
                    model1.setParamName("");
                    model1.setParamType("");
                }
                model1.setCommons(mapping.commons());
                model1.setMethodName(method.getName());
                model1.setMessageId(mapping.messageId());
                methodList.add(model1);
            }
        }
        classModel.setColumns(methodList);
        java.add(classModel);
    }

    public static void generatorTable(String packagePath) {
        Reflections reflection = new Reflections(packagePath);
        // 根据注解，获取所有标记了这个注解的所有类的Class类
        Set<Class<?>> allGameMessageHandlerClass = reflection.getTypesAnnotatedWith(ClientTableFile.class);
        if (allGameMessageHandlerClass == null) {
            return;
        }
        List<CsClassModel<TableModel>> cs = new ArrayList<>();
        for (Class<?> bean : allGameMessageHandlerClass) {
            //生cs和java
            CsClassModel<TableModel> classModel = new CsClassModel<>();
            classModel.setDatetime(DateUtils.format(new Date(System.currentTimeMillis()), DateUtils.DATE_TIME_PATTERN));
            classModel.setClazzName(bean.getSimpleName());
            List<TableModel> fieldList = new ArrayList<>();
            //遍历每个类中的方法
            Field[] fields = bean.getDeclaredFields();
            for (Field field : fields) {
                TableModel model = new TableModel();
                if (TypeUtils.isPrimitive(field.getType().getTypeName())) {
                    String returnType = TypeUtils.getArrType(field.getType().getTypeName(), bean.getName(), field.getName());
                    model.setAttrType(returnType);
                } else {
                    String str = StringUtils.substringAfterLast(field.getType().getTypeName(), ".");
                    str = StringUtils.replace(str, "$", ".");
                    model.setAttrType(str);
                }
                model.setAttrName(field.getName());
                fieldList.add(model);
            }
            classModel.setColumns(fieldList);
            cs.add(classModel);
        }
        TableGenerator.generatorCode(cs);
    }
}
